/*
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "ie_exp_EPUB201_Listener.h"

IE_Exp_EPUB201_Listener::IE_Exp_EPUB201_Listener(PD_Document* doc)
	:m_pSourceDocument(doc),
	 m_nestedCellLevel(0),
	 m_inLink(false),
	 m_tableHelper(doc),
	 m_firstRow(true)
{
	m_pDocument = EPUB_Document::getNewInstance();

	// We need this div because we can`t add spans directly to body
	// By using it we will be sure that were are not breaking any standard
	EPUB_Shared_Element pWrapperDiv(new EPUB_Element(EDE_Div));
	m_pDocument->getDocumentBody()->addChild(pWrapperDiv);
	m_elementStack.push_back(pWrapperDiv);


	m_pSourceDocument->tellListener(static_cast<PL_Listener *>(this));

}

IE_Exp_EPUB201_Listener::~IE_Exp_EPUB201_Listener()
{

}

bool IE_Exp_EPUB201_Listener::populate(PL_StruxFmtHandle sfh,
		const PX_ChangeRecord * pcr)
{

	switch (pcr->getType())
	{
		case PX_ChangeRecord::PXT_InsertSpan:
		{

			const PX_ChangeRecord_Span* pcrs = static_cast<const PX_ChangeRecord_Span*>(pcr);
			PT_BufIndex buffer = pcrs->getBufIndex();
			const UT_UCSChar* pData = m_pSourceDocument->getPointer(buffer);
			UT_UCS4String str(pData, pcrs->getLength());

			if (m_inLink || (m_nestedCellLevel > 0))
			{
				m_elementStack.back()->setValue(UT_UTF8String(str));
			} else
			{
				EPUB_Shared_Element spanElement(new EPUB_Element(
						EDE_Span, UT_UTF8String(str)));
				m_elementStack.back()->addChild(spanElement);

			}
			break;
		}
		case PX_ChangeRecord::PXT_InsertObject:
		{
			const PX_ChangeRecord_Object * pcro = static_cast<const PX_ChangeRecord_Object *> (pcr);
			UT_DEBUGMSG(("RUDYJ: PXT_InsertObject\n"));
			PT_AttrPropIndex api = pcr->getIndexAP();
			const PP_AttrProp* pAP = NULL;
			bool bHaveProp = m_pSourceDocument->getAttrProp(api,&pAP);

			const gchar* szValue;
			const gchar* szName;

			// Current element that we`ll add to the DOM
			EPUB_Shared_Element currentElement;
			bool needPush = false;

			switch (pcro->getObjectType())
			{
				case PTO_Field:
					break;
				case PTO_Hyperlink:
				{
					if (m_inLink == true)
					{
						m_inLink = false;
						m_elementStack.pop_back();
						return true;
					} else
					{
						m_inLink = true;
						needPush = true;
					}
					currentElement = EPUB_Shared_Element(
							new EPUB_Element(EDE_Hyperlink));


					// TODO: Add href attribute to string here
					break;
				}
				case PTO_Image:
				{
					currentElement = EPUB_Shared_Element(
							new EPUB_Element(EDE_Image));

					const UT_ByteBuf *pData;

					const gchar *szDataId;
					pAP->getAttribute((const gchar*)"dataid", szDataId);
					std::string extStr;
					m_pSourceDocument->getDataItemFileExtension(szDataId,extStr, true);
					m_pSourceDocument->getDataItemDataByName(szDataId, &pData,NULL,NULL);

					UT_UTF8String dataId = UT_UTF8String(szDataId);
					UT_UTF8String extension = UT_UTF8String(extStr.c_str());
					UT_UTF8String name = dataId.escapeXML() + extension;

					EPUB_Shared_EmbeddedFile imgFile(new EPUB_EmbeddedFile(name, pData,
							EFT_Image));
					m_pDocument->addFile(imgFile);
					UT_UTF8String *fullPath = new UT_UTF8String(UT_UTF8String("OEBPS/images/") + name);
					currentElement->setAttribute("src",fullPath);
					needPush = false;
					break;
				}
				case PTO_Bookmark:
					break;
				default:
					break;
			}

			if (currentElement != 0)
			{
				UT_DEBUGMSG(("RUDYJ: Added to: %s\n", m_elementStack.back()->getName().utf8_str()));
				m_elementStack.back()->addChild(currentElement);

				if (needPush)
				{
					m_elementStack.push_back(currentElement);
				}
			}

			break;
		}
		case PX_ChangeRecord::PXT_InsertFmtMark:
			break;
		default:
			break;
	}


	return true;
}
bool IE_Exp_EPUB201_Listener::populateStrux(PL_StruxDocHandle sdh,
		const PX_ChangeRecord * pcr, PL_StruxFmtHandle * psfh)
{
	if(pcr->getType() != PX_ChangeRecord::PXT_InsertStrux)
		return false;

	const PX_ChangeRecord_Strux* pcrx = static_cast<const PX_ChangeRecord_Strux *> (pcr);

	PT_AttrPropIndex api = pcr->getIndexAP();
	const PP_AttrProp* pAP = NULL;
	bool bHaveProp = m_pSourceDocument->getAttrProp(api,&pAP);
	UT_DEBUGMSG(("RUDYJ: PXT_InsertStrux\n"));



	switch (pcrx->getStruxType())
	{
		case PTX_Section:
			UT_DEBUGMSG(("RUDYJ: PTX_Section\n"));
			break;
		case PTX_Block:
			UT_DEBUGMSG(("RUDYJ: PTX_Block\n"));
			break;
		case PTX_SectionHdrFtr:
			UT_DEBUGMSG(("RUDYJ: PTX_SectionHdrFtr\n"));
			break;
		case PTX_SectionEndnote:
			UT_DEBUGMSG(("RUDYJ: PTX_SectionEndnote\n"));
			break;
		case PTX_SectionTable:
		{
			m_tableHelper.OpenTable(sdh, pcr->getIndexAP());
			EPUB_Shared_Element tableElement(
					new EPUB_Element(EDE_Table));
			tableElement->setAttribute("border", new UT_UTF8String("1"));
			m_elementStack.back()->addChild(tableElement);
			m_elementStack.push_back(tableElement);
			m_firstRow = true;

		}
		break;
		case PTX_SectionCell:
		{
			m_tableHelper.OpenCell(api);
			m_nestedCellLevel++;
			// We need to create new row element if we met new row or there wasn`t any
			// rows yet
			if ( m_firstRow || m_tableHelper.isNewRow())
			{
				if (!m_firstRow)
				{
					m_elementStack.pop_back();
				} else
				{
					m_firstRow = false;
				}
				EPUB_Shared_Element rowElement(new EPUB_Element(EDE_TableRow));
				m_elementStack.back()->addChild(rowElement);
				m_elementStack.push_back(rowElement);
			}
			EPUB_Shared_Element cellElement(
					new EPUB_Element(EDE_TableCell));
			m_elementStack.back()->addChild(cellElement);
			m_elementStack.push_back(cellElement);

		}
		break;
		case PTX_SectionFootnote:
			UT_DEBUGMSG(("RUDYJ: PTX_SectionFootnote\n"));
			break;
		case PTX_SectionFrame:
			UT_DEBUGMSG(("RUDYJ: PTX_SectionFrame\n"));
			break;
		case PTX_EndCell:
			// Pop back table cell
			m_elementStack.pop_back();
			m_nestedCellLevel--;
			m_tableHelper.CloseCell();
			break;
		case PTX_EndTable:
			// Pop back row
			m_elementStack.pop_back();
			// Pop back table
			m_elementStack.pop_back();
			m_tableHelper.CloseTable();
			break;
		case PTX_EndFootnote:
			UT_DEBUGMSG(("RUDYJ: PTX_Footnote\n"));
			break;
		case PTX_EndEndnote:
			UT_DEBUGMSG(("RUDYJ: PTX_EndEndnote\n"));
			break;
		case PTX_EndFrame:
			UT_DEBUGMSG(("RUDYJ: PTX_EndFrame\n"));
			break;
		case PTX_SectionMarginnote:
		case PTX_SectionAnnotation:
		case PTX_SectionTOC:
		case PTX_EndMarginnote:
		case PTX_EndAnnotation:
		case PTX_EndTOC:
		default:
			return true;
	}

	return true;
}
bool IE_Exp_EPUB201_Listener::change(PL_StruxFmtHandle sfh, const PX_ChangeRecord * pcr)
{

}
bool IE_Exp_EPUB201_Listener::insertStrux(PL_StruxFmtHandle sfh,
		const PX_ChangeRecord * pcr, PL_StruxDocHandle sdhNew,
		PL_ListenerId lid,
		void (* pfnBindHandles)(PL_StruxDocHandle sdhNew, PL_ListenerId lid,
		PL_StruxFmtHandle sfhNew))
{

}
bool IE_Exp_EPUB201_Listener::signal(UT_uint32 Signal)
{

}

EPUB_Shared_Document IE_Exp_EPUB201_Listener::getDocument()
{
	return m_pDocument;
}

